package com.oristand.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.oristand.annotation.RedisCache;
import com.oristand.mapper.ManufacturerMapper;
import com.oristand.mapper.ProductMapper;
import com.oristand.mapper.PropertyMapper;
import com.oristand.mapper.StoreProductMapper;
import com.oristand.pojo.Manufacturer;
import com.oristand.pojo.Product;
import com.oristand.pojo.Property;
import com.oristand.pojo.StoreProduct;
import com.oristand.pojo.vo.ProductVo;
import com.oristand.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 商品接口的实现类,里面实现的service层的逻辑
 * <p>
 * 使用了mapper层的三个接口
 * </p>
 *
 * @author shiyjian
 * @version 1.0
 * @date 2021/11/29 14:38
 * @see com.oristand.service.ProductService
 */
@Service
public class ProductServiceImpl implements ProductService {

    private ProductMapper productMapper;

    private PropertyMapper propertyMapper;

    private ManufacturerMapper manufacturerMapper;

    private StoreProductMapper storeProductMapper;

    @Autowired
    public void setStoreProductMapper(StoreProductMapper storeProductMapper) {
        this.storeProductMapper = storeProductMapper;
    }

    @Autowired
    public void setPropertyMapper(PropertyMapper propertyMapper) {
        this.propertyMapper = propertyMapper;
    }

    @Autowired
    public void setManufacturerMapper(ManufacturerMapper manufacturerMapper) {
        this.manufacturerMapper = manufacturerMapper;
    }

    @Autowired
    public void setProductMapper(ProductMapper productMapper) {
        this.productMapper = productMapper;
    }

    /**
     * 根据id查询单个商品的全部信息
     *
     * @return 返回商品对象
     */
    @RedisCache(key = "product", expired = 60L)
    @Override
    public ProductVo findProductVoById(Integer productId) {
        if (productId != null) {
            Product product = productMapper.selectById(productId);
            return findProductVoByProduct(product);
        }
        return null;
    }

    /**
     * 查询所有的商品对象,包含商品的具体属性信息
     *
     * @return 返回product的list集合
     */
    @RedisCache(key = "productVoList", expired = 60L)
    @Override
    public List<ProductVo> findProductVoList() {
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        //必须是status为1的商品,表示该商品可以被销售
        productQueryWrapper.eq("status", 1);
        List<Product> productList = productMapper.selectList(productQueryWrapper);
        List<ProductVo> productVos = new ArrayList<>();
        productList.forEach(value -> productVos.add(findProductVoByProduct(value)));
        if (!productList.isEmpty()) {
            return productVos;
        }
        return null;
    }

    /**
     * 根据商品的id更新商品,返回值是1或0
     *
     * @param product 商品对象
     * @return 返回更新影响的行数
     */
    @RedisCache(read = false)
    @Override
    public int updateProductById(Product product) {
        return productMapper.updateById(product);
    }

    /**
     * 删除商品时要先删除商品,其次再删除商品的属性
     *
     * @param id 商品id
     * @return 返回删除影响的行数, 返回值是2或0
     */
    @RedisCache(read = false)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteProductById(Integer id) {
        //如果id不为空才能删除
        if (id != null) {
            QueryWrapper<StoreProduct> storeProductQueryWrapper = new QueryWrapper<>();
            storeProductQueryWrapper.eq("product_id",id);
            storeProductMapper.delete(storeProductQueryWrapper);
            //先删除商品的本身
            Product product = productMapper.selectById(id);
            if (product != null) {
                //定义影响的行数
                int rows = 0;
                //在删除商品的属性
                rows += productMapper.deleteById(id);
                if (product.getPropertyId() != null) {
                    rows += propertyMapper.deleteById(product.getPropertyId());
                }
                return rows;
            }
        }
        return 0;
    }

    /**
     * 插入商品
     *
     * @param product 商品对象
     * @return 返回值是影响的行数, 1或0
     */
    @RedisCache(read = false)
    @Override
    public Product insertProduct(Product product) {
        //uuid自动生成
        String uuid = UUID.randomUUID().toString();
        product.setProductUuid(uuid);
        if (product.getProductCreateTime() == null) {
            product.setProductCreateTime(new Date());
        }
        //获取用户输入的sku,如果sku重复说明该商品已经存在了,不能添加
        String productSku = product.getProductSku();
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        productQueryWrapper
                .eq("product_sku", productSku);
        Long sameSkuOrUuidCount = productMapper.selectCount(productQueryWrapper);
        if (sameSkuOrUuidCount > 0) {
            return null;
        } else {
            productMapper.insert(product);
            QueryWrapper<Product> productUuid = new QueryWrapper<Product>().eq("product_uuid", uuid);
            return productMapper.selectList(productUuid).get(0);
        }
    }

    /**
     * 分页查询商品
     *
     * @param page 当前页
     * @param size 当前页的大小
     * @return 返回商品的详细信息
     */
    @RedisCache(key = "productByPage", expired = 90)
    @Override
    public Page<ProductVo> findProductByPage(Integer page, Integer size) {
        if (page > 0) {
            //计算当前是在数据库中的第几行,因为下面的Page对象传的参数是当前行数,和数据条数
            int current = (page - 1) * size;
            QueryWrapper<Product> statusWrapper = new QueryWrapper<Product>().eq("status", 1);
            //查询出所有的商品对象
            Page<Product> pageProduct = productMapper.selectPage(new Page<>(current, size), statusWrapper);
            List<ProductVo> productVos = new ArrayList<>(16);
            //根据商品对象在循环遍历,用商品的厂家外键和属性外键再次去查询出对象然后进行vo封装
            for (Product record : pageProduct.getRecords()) {
                productVos.add(findProductVoByProduct(record));
            }
            //给商品对象设置数据总条数和总页数
            Page<ProductVo> productVoPage = new Page<>(current, size);
            Long total = productMapper.selectCount(statusWrapper);
            productVoPage.setTotal(total);
            if (total % size == 0) {
                productVoPage.setPages(total / size);
            } else {
                productVoPage.setPages(total / size + 1);
            }
            productVoPage.setRecords(productVos);
            return productVoPage;
        }
        return null;
    }

    @RedisCache(key = "productVoByLike",expired = 60)
    @Override
    public List<ProductVo> findProductVoLikeSkuOrName(String str) {
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        productQueryWrapper.like("product_sku",str)
                .or()
                .like("product_name",str);
        List<Product> productList = productMapper.selectList(productQueryWrapper);
        List<ProductVo> productVos = new ArrayList<>();
        for (Product product : productList) {
            productVos.add(findProductVoByProduct(product));
        }
        return productVos;
    }

    private ProductVo findProductVoByProduct(Product product) {
        ProductVo productVo = new ProductVo();
        Integer propertyId = product.getPropertyId();
        Integer manufacturerId = product.getManufacturerId();
        if (propertyId == null) {
            productVo.setProperty(null);
        } else {
            Property property = propertyMapper.selectById(propertyId);
            productVo.setProperty(property);
        }
        if (manufacturerId == null) {
            productVo.setManufacturer(null);
        } else {
            Manufacturer manufacturer = manufacturerMapper.selectById(manufacturerId);
            productVo.setManufacturer(manufacturer);
        }
        productVo.setProduct(product);
        return productVo;
    }

}
